﻿using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Windows;

namespace SharpSoft.WPF
{
    public class WindowsHelper
    {
        #region AutoStartup

        /// <summary>
        /// 在注册表注册开机自动运行
        /// </summary>
        /// <param name="key"></param>
        /// <param name="exePath"></param>
        public static void AutoRunWidthRegistry(string key, string exePath = null)
        {
            if (exePath == null)
            {
                exePath = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName;
            }
            RegistryKey rk = Registry.CurrentUser;//当前用户的启动项。如果设为LocalMachine（所有用户）则需要管理员权限
            RegistryKey rk2 = rk.CreateSubKey(@"Software\Microsoft\Windows\CurrentVersion\Run");
            rk2.SetValue(key, $"\"{exePath}\"");
            rk2.Close();
            rk.Close();
        }
        /// <summary>
        /// 取消注册表里的开机自动运行
        /// </summary>
        /// <param name="key"></param>
        /// <param name="exePath"></param>
        public static void AbortAutoRunWidthRegistry(string key, string exePath)
        {
            RegistryKey rk = Registry.CurrentUser;
            RegistryKey rk2 = rk.CreateSubKey(@"Software\Microsoft\Windows\CurrentVersion\Run");
            var value = rk2.GetValue(key);
            if (value is string val && string.Compare(exePath, val) == 0)
            {
                rk2.DeleteValue(key, false);
            }

            rk2.Close();
            rk.Close();

        }
        /// <summary>
        /// 获取程序是否在注册表里注册了开机自动运行
        /// </summary>
        /// <param name="key"></param>
        /// <param name="exePath"></param>
        /// <returns></returns>
        public static bool IsAutoRunWidthRegistry(string key, string exePath)
        {
            RegistryKey rk = Registry.CurrentUser;
            RegistryKey rk2 = rk.CreateSubKey(@"Software\Microsoft\Windows\CurrentVersion\Run");
            var value = rk2.GetValue(key);
            bool isautorun = false;
            if (value is string val && val.ToLower() == $"\"{exePath.ToLower()}\"")
            {
                isautorun = true;
            }

            rk2.Close();
            rk.Close();
            return isautorun;
        }
        #endregion


        public static void CmdRun(string cmd)
        {
            cmd = cmd.Replace("&", "^&");
            System.Diagnostics.Process p = new System.Diagnostics.Process();
            p.StartInfo.FileName = "cmd.exe";
            p.StartInfo.UseShellExecute = false;
            p.StartInfo.RedirectStandardInput = true;
            p.StartInfo.RedirectStandardOutput = false;
            p.StartInfo.RedirectStandardError = true;
            p.StartInfo.CreateNoWindow = true;
            p.Start();

            //向cmd窗口发送输入信息 后面的&exit告诉cmd运行好之后就退出
            p.StandardInput.WriteLine(cmd);
            p.StandardInput.AutoFlush = true;
            p.WaitForExit();//等待程序执行完退出进程
            p.Close();
        }

        /// <summary>
        /// 使用CMD打开对象
        /// </summary>
        /// <param name="path"></param>
        public static void OpenUseCmd(string path)
        {
            string target = path;
            //target = target.Replace("^", "^^");
            //target = target.Replace(">", "^>");
            //target = target.Replace("<", "^<");
            //target = target.Replace("=", "^=");
            //target = target.Replace("|", "^|");
            //target = target.Replace("'", "^'");
            //target = target.Replace("`", "^`");
            //target = target.Replace(",", "^,");
            //target = target.Replace(";", "^;");
            //target = target.Replace("(", "^(");
            //target = target.Replace(")", "^)");
            //target = target.Replace("\"", "\\\""); 
            target = target.Replace("&", "^&");
            System.Diagnostics.Process p = new System.Diagnostics.Process();
            p.StartInfo.FileName = "cmd.exe";
            p.StartInfo.UseShellExecute = false;
            p.StartInfo.RedirectStandardInput = true;
            p.StartInfo.RedirectStandardOutput = false;
            p.StartInfo.RedirectStandardError = true;
            p.StartInfo.CreateNoWindow = true;
            p.Start();

            //向cmd窗口发送输入信息 后面的&exit告诉cmd运行好之后就退出
            p.StandardInput.WriteLine("start " + target + "&exit");
            p.StandardInput.AutoFlush = true;
            p.WaitForExit();//等待程序执行完退出进程
            p.Close();
        }
        /// <summary>
        /// 打开资源管理器
        /// </summary>
        /// <param name="path"></param>
        public static void OpenExplorer(string path)
        {
            System.Diagnostics.ProcessStartInfo psi = new System.Diagnostics.ProcessStartInfo("Explorer.exe");

            if (!string.IsNullOrEmpty(path))
            {
                if (System.IO.Directory.Exists(path))
                {
                    psi.Arguments = "/e," + path;
                }
                else if (System.IO.File.Exists(path))
                {
                    psi.Arguments = "/e,/select," + path;
                }

            }

            System.Diagnostics.Process.Start(psi);
        }

        #region 音量控制
        [DllImport("user32.dll")]
        static extern void keybd_event(byte bVk, byte bScan, UInt32 dwFlags, UInt32 dwExtraInfo);

        [DllImport("user32.dll")]
        static extern Byte MapVirtualKey(UInt32 uCode, UInt32 uMapType);

        private const byte VK_VOLUME_MUTE = 0xAD;
        private const byte VK_VOLUME_DOWN = 0xAE;
        private const byte VK_VOLUME_UP = 0xAF;
        private const UInt32 KEYEVENTF_EXTENDEDKEY = 0x0001;
        private const UInt32 KEYEVENTF_KEYUP = 0x0002;

        /// <summary>
        /// 加大系统音量
        /// </summary>
        public static void VolumeUp()
        {
            keybd_event(VK_VOLUME_UP, MapVirtualKey(VK_VOLUME_UP, 0), KEYEVENTF_EXTENDEDKEY, 0);
            Thread.Sleep(50);
            keybd_event(VK_VOLUME_UP, MapVirtualKey(VK_VOLUME_UP, 0), KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
        }

        /// <summary>
        /// 减小系统音量
        /// </summary>
        public static void VolumeDown()
        {
            keybd_event(VK_VOLUME_DOWN, MapVirtualKey(VK_VOLUME_DOWN, 0), KEYEVENTF_EXTENDEDKEY, 0);
            Thread.Sleep(50);
            keybd_event(VK_VOLUME_DOWN, MapVirtualKey(VK_VOLUME_DOWN, 0), KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
        }

        /// <summary>
        ///  静音
        /// </summary>
        public static void VolumeMute()
        {
            keybd_event(VK_VOLUME_MUTE, MapVirtualKey(VK_VOLUME_MUTE, 0), KEYEVENTF_EXTENDEDKEY, 0);
            Thread.Sleep(50);
            keybd_event(VK_VOLUME_MUTE, MapVirtualKey(VK_VOLUME_MUTE, 0), KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
        }
        #endregion


        #region 硬件信息


        #endregion

        #region 阻止休眠
        /// <summary>
        /// Enables an application to inform the system that it is in use, thereby preventing the system from entering sleep or turning off the display while the application is running.
        /// </summary>
        [DllImport("kernel32")]
        private static extern ExecutionState SetThreadExecutionState(ExecutionState esFlags);

        [Flags]
        private enum ExecutionState : uint
        {
            /// <summary>
            /// Forces the system to be in the working state by resetting the system idle timer.
            /// </summary>
            SystemRequired = 0x01,

            /// <summary>
            /// Forces the display to be on by resetting the display idle timer.
            /// </summary>
            DisplayRequired = 0x02,

            /// <summary>
            /// This value is not supported. If <see cref="UserPresent"/> is combined with other esFlags values, the call will fail and none of the specified states will be set.
            /// </summary>
            [Obsolete("This value is not supported.")]
            UserPresent = 0x04,

            /// <summary>
            /// Enables away mode. This value must be specified with <see cref="Continuous"/>.
            /// <para />
            /// Away mode should be used only by media-recording and media-distribution applications that must perform critical background processing on desktop computers while the computer appears to be sleeping.
            /// </summary>
            AwaymodeRequired = 0x40,

            /// <summary>
            /// Informs the system that the state being set should remain in effect until the next call that uses <see cref="Continuous"/> and one of the other state flags is cleared.
            /// </summary>
            Continuous = 0x80000000,
        }
        /// <summary>
        /// 设置此线程此时开始一直将处于运行状态，此时计算机不应该进入睡眠状态。
        /// 此线程退出后，设置将失效。
        /// 如果需要恢复，请调用 <see cref="RestoreForCurrentThread"/> 方法。
        /// </summary>
        /// <param name="keepDisplayOn">
        /// 表示是否应该同时保持屏幕不关闭。
        /// 对于游戏、视频和演示相关的任务需要保持屏幕不关闭；而对于后台服务、下载和监控等任务则不需要。
        /// </param>
        public static void PreventForCurrentThread(bool keepDisplayOn = true)
        {
            SetThreadExecutionState(keepDisplayOn
                ? ExecutionState.Continuous | ExecutionState.SystemRequired | ExecutionState.DisplayRequired
                : ExecutionState.Continuous | ExecutionState.SystemRequired);
        }

        /// <summary>
        /// 恢复此线程的运行状态，操作系统现在可以正常进入睡眠状态和关闭屏幕。
        /// </summary>
        public static void RestoreForCurrentThread()
        {
            SetThreadExecutionState(ExecutionState.Continuous);
        }

        /// <summary>
        /// 重置系统睡眠或者关闭屏幕的计时器，这样系统睡眠或者屏幕能够继续持续工作设定的超时时间。
        /// </summary>
        /// <param name="keepDisplayOn">
        /// 表示是否应该同时保持屏幕不关闭。
        /// 对于游戏、视频和演示相关的任务需要保持屏幕不关闭；而对于后台服务、下载和监控等任务则不需要。
        /// </param>
        public static void ResetIdle(bool keepDisplayOn = true)
        {
            SetThreadExecutionState(keepDisplayOn
                ? ExecutionState.SystemRequired | ExecutionState.DisplayRequired
                : ExecutionState.SystemRequired);
        }

        #endregion
    }
}
